﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace BilingualSentIndexing
{
    class SentIdPairReader
    {
        private BinaryReader br;
        private StreamReader sr;
        private long lSizeInMemory = 0;
        private int iMaxSentPairSize = 8192;
        private int[] aiData;

        private object privateObject = new object();
        public void Open(string fileName, double fPercentInMemory)
        {
            if (fPercentInMemory < 0.0)
            {
                fPercentInMemory = 0.0;
            }
            if (fPercentInMemory > 1.0)
            {
                fPercentInMemory = 1.0;
            }

            FileInfo info = new FileInfo(fileName);
            lSizeInMemory = (long)(info.Length * fPercentInMemory);
       //     lSizeInMemory -= iMaxSentPairSize;
            if (lSizeInMemory < 0)
            {
                lSizeInMemory = 0;
            }
            else
            {
                lSizeInMemory = lSizeInMemory + (4 - (lSizeInMemory % 4));
                if (lSizeInMemory > info.Length)
                {
                    lSizeInMemory = info.Length;
                }
            }

            StreamReader reader = new StreamReader(fileName);
            BinaryReader reader2 = new BinaryReader(Stream.Synchronized(reader.BaseStream));


            byte[] abData;
            abData = reader2.ReadBytes((int)lSizeInMemory);
            reader2.Close();
            reader.Close();


            aiData = new int[abData.Length / 4];
            System.Buffer.BlockCopy(abData, 0, aiData, 0, abData.Length * sizeof(byte));



            sr = new StreamReader(fileName);
            br = new BinaryReader(FileStream.Synchronized(sr.BaseStream));

        }

        public void Read(out int [] aiEnglishLine, out int [] aiChineseLine, out int sentPairOffset, int offset)
        {
            if (offset + iMaxSentPairSize >= (int)lSizeInMemory)
            {
                ReadFromDisk(out aiEnglishLine, out aiChineseLine, out sentPairOffset, offset);
            }
            else
            {
                ReadFromMemory(out aiEnglishLine, out aiChineseLine, out sentPairOffset, offset);
            }
        }

        private void ReadFromDisk(out int [] englishLine, out int [] chineseLine, out int sentPairOffset, int offset)
        {
            lock (privateObject)
            {
                br.BaseStream.Seek(offset, SeekOrigin.Begin);

                int num;
                byte[] abData;

                sentPairOffset = br.ReadInt32();

                num = br.ReadInt32();
                abData = br.ReadBytes(num * 4);
                englishLine = new int[num];
                System.Buffer.BlockCopy(abData, 0, englishLine, 0, abData.Length * sizeof(byte));

                num = br.ReadInt32();
                abData = br.ReadBytes(num * 4);
                chineseLine = new int[num];
                System.Buffer.BlockCopy(abData, 0, chineseLine, 0, abData.Length * sizeof(byte));

            }
        }

        private void ReadFromMemory(out int[] englishLine, out int[] chineseLine, out int sentPairOffset, int offset)
        {
            int iOffset;
            iOffset = offset / 4;

            sentPairOffset = aiData[iOffset];
            iOffset++;

            int num;
            num = aiData[iOffset];
            iOffset++;
            englishLine = new int[num];
            System.Buffer.BlockCopy(aiData, iOffset * 4, englishLine, 0, num * sizeof(int));

            iOffset += num;
            
            num = aiData[iOffset];
            iOffset++;
            chineseLine = new int[num];
            System.Buffer.BlockCopy(aiData, iOffset * 4, chineseLine, 0, num * sizeof(int));
        }
    }
}
